﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Mail;
using System.Security.Cryptography.X509Certificates;

namespace NHINDirect
{
    public class NHINDAddressCollection : ObjectCollection<NHINDAddress>
    {
        public const TrustEnforcementStatus DefaultMinTrustStatus = TrustEnforcementStatus.Success_Offline;
        
        public NHINDAddressCollection()
        {
        }

        public IEnumerable<X509Certificate2> Certificates
        {
            get
            {
                return from address in this
                    where address.HasCertificate
                    select address.Certificate;
            }
        }
        
        public X509Certificate2 GetFirstCertificate()
        {
            for (int i = 0, count = this.Count; i < count; ++i)
            {
                NHINDAddress address = this[i];
                if (address.HasCertificate)
                {
                    return address.Certificate;
                }                
            }
            return null;
        }
        
        public X509Certificate2Collection GetCertificates()
        {
            X509Certificate2Collection certs = new X509Certificate2Collection();
            certs.Add(this.Certificates);
            return certs;
        }
                
        /// <summary>
        /// Get the trustworthy members of this collection
        /// </summary>
        public IEnumerable<NHINDAddress> GetTrusted()
        {
            return this.GetTrusted(NHINDAddressCollection.DefaultMinTrustStatus);
        }

        public IEnumerable<NHINDAddress> GetTrusted(TrustEnforcementStatus minTrustStatus)
        {
            return from address in this
                   where address.IsTrusted(minTrustStatus)
                   select address;
        }
        
        public IEnumerable<NHINDAddress> GetUntrusted()
        {
            return this.GetUntrusted(NHINDAddressCollection.DefaultMinTrustStatus);
        }

        public IEnumerable<NHINDAddress> GetUntrusted(TrustEnforcementStatus minTrustStatus)
        {
            return from address in this
                   where !address.IsTrusted(minTrustStatus)
                   select address;
        }
        
        /// <summary>
        /// Does this collection of NHINDAddress contain only trustworthy addresses? 
        /// </summary>
        /// <returns></returns>        
        public bool IsTrusted()
        {
            return this.IsTrusted(NHINDAddressCollection.DefaultMinTrustStatus);
        }

        public bool IsTrusted(TrustEnforcementStatus minTrustStatus)
        {
            return this.All(x => x.IsTrusted(minTrustStatus));
        }
        
        public void RemoveUntrusted()
        {
            this.RemoveUntrusted(NHINDAddressCollection.DefaultMinTrustStatus);
        }
        
        public void RemoveUntrusted(TrustEnforcementStatus minTrustStatus)
        {
            // Remove anybody who is not trusted
            this.RemoveExcept(x => x.IsTrusted(minTrustStatus));
        }
        
        public MailAddressCollection ToMailAddressCollection()
        {
            MailAddressCollection addresses = new MailAddressCollection();
            for (int i = 0, count = this.Count; i < count; ++i)
            {
                addresses.Add(this[i]);
            }
            
            return addresses;
        }

        public override string ToString()
        {
            return this.ToMailAddressCollection().ToString();
        }
        
        internal static NHINDAddressCollection Create(IEnumerable<NHINDAddress> source)
        {
            NHINDAddressCollection addresses = null;
            foreach(NHINDAddress address in source)
            {
                if (addresses == null)
                {
                    addresses = new NHINDAddressCollection();
                }
                addresses.Add(address);
            }
            
            return addresses;
        }
    }
}
